/**********************************************************************
 *** *                                                            * ***
 *** *  Copyright (c) 2013 Harmonia Holdings Group LLC            * ***
 *** *                                                            * ***
 *** * Permission is hereby granted to use, modify, copy, and     * ***
 *** * distribute this software and its documentation for any     * ***
 *** * purpose only without profit, provided that the above       * ***
 *** * Copyright Notice appears in all copies and that both the   * ***
 *** * Copyright Notice and this Permission Notice appears in     * ***
 *** * every copy of supporting documentation.  No title to nor   * ***
 *** * ownership of the software is transferred hereby.  The name * ***
 *** * of Harmonia Holdings Group LLC shall not be used in        * ***
 *** * advertising or publicity related to the distribution of    * ***
 *** * the software without specific, written, prior permission.  * ***
 *** * This software is provided as-delivered without expressed   * ***
 *** * or implied warranty.  Harmonia Holdings Group LLC          * ***
 *** * makes no representation about the suitability of this      * ***
 *** * software for any purpose and accepts no responsibility for * ***
 *** * its use.                                                   * ***
 *** *                                                            * ***
 *** ************************************************************** ***
 *** *                                                            * ***
 *** * This program is free software; you can redistribute it     * ***
 *** * and/or modify it under the terms of the GNU General Public * ***
 *** * License as published by the Free Software Foundation;      * ***
 *** * either version 2 of the License, or (at your option) any   * ***
 *** * later version.                                             * ***
 *** *                                                            * ***
 *** * This program is distributed in the hope that it will be    * ***
 *** * useful, but WITHOUT ANY WARRANTY; without even the implied * ***
 *** * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR    * ***
 *** * PURPOSE.  See the GNU General Public License for more      * ***
 *** * details.                                                   * ***
 *** *                                                            * ***
 *** * You should have received a copy of the GNU General Public  * ***
 *** * License along with this program; if not, write to the Free * ***
 *** * Software Foundation, Inc., 51 Franklin Street, Fifth       * ***
 *** * Floor, Boston, MA 02110-1301, USA.                         * ***
 *** *                                                            * ***
 *** * For more information: http://www.gnu.org/licenses/gpl.html * ***
 *** *                                                            * ***
 **********************************************************************/
package org.etexascode.interrep.datamodel.utils;

import java.awt.Polygon;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/**
 * A utility class for converting various types into strings in a uniform way.
 * This class was originally envisioned to help the toString methods in the datamodel,
 * but could easily be used elsewhere in the code.
 * 
 * @author ablatt
 * @author bmauldon
 *
 */
public class UtilsStringOnModel {
	public final static Charset UTF8_CHARSET = Charset.forName("UTF-8");
	/**
	 * Add a double to a string builder while giving that double a title (name) in a uniform way.
	 * @param addTo
	 * @param toAdd
	 * @param title
	 */
	public static void addDouble(StringBuilder addTo, double toAdd, String title) {
		addTo.append(title);
		addTo.append(" = ");
		addTo.append(toAdd);
		addTo.append("\n");
	}
	/**
	 * Add an int to a string builder while giving that int a title (name) in a uniform way.
	 * @param addTo
	 * @param toAdd
	 * @param title
	 */
	public static void addInt(StringBuilder addTo, int toAdd, String title) {
		addTo.append(title);
		addTo.append(" = ");
		addTo.append(toAdd);
		addTo.append("\n");
	}
	/**
	 * Add a list to a string builder while giving that list a title (name) in a uniform way.
	 * @param addTo
	 * @param toAdd
	 * @param listTitle
	 */
	public static <T> void addList(StringBuilder addTo, List<T> toAdd, String listTitle) {
		for(T elem:toAdd) {
			addListElement(addTo, elem, listTitle);
		}
	}
	
	/**
	 * Adds a set to a string builder while giving that set a title (name) in a uniform way.
	 * @param addTo
	 * @param toAdd
	 * @param listTitle
	 */
	public static <T> void addSet(StringBuilder addTo, Set<T> toAdd, String listTitle) {
		Iterator<T> itr = toAdd.iterator();
		while(itr.hasNext()) {
			addListElement(addTo, itr.next(), listTitle);
		}
	}
	/**
	 * Add a list element to a string builder while giving that list element a title (name) in a uniform way.
	 * @param addTo
	 * @param toAdd
	 * @param listTitle
	 */
	public static <T> void addListElement(StringBuilder addTo, T toAdd, String listTitle) {
		addTo.append(listTitle);
		addTo.append(" Element = ");
		addTo.append(toAdd.toString());
		addTo.append("\n");
	}
	/**
	 * Add a map to a string builder while giving that map a title (name) in a uniform way.
	 * @param addTo
	 * @param value
	 * @param mapTitle
	 */
	public static <E> void addMap(StringBuilder addTo, Map<Integer, E> value, String mapTitle) {
		for(Entry<Integer, E> entry:value.entrySet()) {
			addMapKeyValue(addTo, entry.getKey(),entry.getValue(), mapTitle);
		}
	}
	/**
	 * Add a map's key value pair to a string builder while giving that pair a title (name) in a uniform way.
	 * @param addTo
	 * @param key
	 * @param value
	 * @param mapTitle
	 */
	public static <T> void addMapKeyValue(StringBuilder addTo, Integer key, T value, String mapTitle) {
		addTo.append(mapTitle);
		addTo.append(" Map: key = ");
		addTo.append(key.intValue());
		addTo.append("\n     value = ");
		addTo.append(value.toString());
		addTo.append("\n");
	}
	/**
	 * Add a string to a string builder while giving that string a title (name) in a uniform way.
	 * @param addTo
	 * @param toAdd
	 * @param title
	 */
	public static void addString(StringBuilder addTo, String toAdd, String title) {
		addTo.append(title);
		addTo.append(" = ");
		addTo.append(toAdd);
		addTo.append("\n");
	}
	/**
	 * Build a string out of a point (x, y pair).
	 * @param x
	 * @param y
	 * @return String
	 * 
	 */
	public static String buildPointString(int x, int y) {
		StringBuilder ret = new StringBuilder("(");

		ret.append(x);
		ret.append(", ");
		ret.append(y);
		ret.append(")\n");

		return ret.toString();
	}
	/**
	 * Build a string out of a polygon.
	 * @param p
	 * @return String
	 */
	public static String buildPolygonString(Polygon p) {
		StringBuilder ret = new StringBuilder();

		for(int i = 0; i < p.npoints; i++) {
			ret.append(buildPointString(p.xpoints[i], p.ypoints[i]));
		}

		return ret.toString();
	}
	/**
	 * Decode a UTF8 byte buffer into a string.
	 * @param bytes
	 * @return String
	 */
	public static String decodeUTF8(byte[] bytes){
		return new String(bytes, UTF8_CHARSET);
	}

	/**
	 * Converts a map (toConvert) into a string labeled by the title (title).
	 * @param toConvert
	 * @param title
	 * @return The converted map.
	 */
	public static <E, F> String addMap(Map<E, F> toConvert, String title) {
		StringBuilder ret = new StringBuilder();

		ret.append("Map: ");
		ret.append(title);
		ret.append("\n");

		for(Entry<E, F> entry:toConvert.entrySet()) {
			ret.append(entry.getKey().toString());
			ret.append(": ");
			ret.append(entry.getValue().toString());
			ret.append("\n");
		}

		return ret.toString();
	}
	
	/**
	 * Converts a list to a human readable string.
	 * @param toConvert
	 * @param title
	 * @return The string form of list.
	 */
	public static <E> String listToString(List<E> toConvert, String title) {
		StringBuilder ret = new StringBuilder();

		ret.append("List: ");
		ret.append(title);
		ret.append("\n");
		
		for(E item:toConvert) {
			ret.append("Entry: ");
			ret.append(item.toString());
			ret.append("\n");
		}
		
		return ret.toString();
	}
}
